using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.Skins;
using DevExpress.LookAndFeel;
using DevExpress.UserSkins;
using DevExpress.XtraEditors;
using RADB;
using System.IO;


namespace Waiter
{
    public partial class frmWaiter : XtraForm
    {
        IDataTransfer DTO;
        DataTable tablelist;
        int currWaiter = 1;
        int currTable = 1;
        public frmWaiter()
        {
            InitializeComponent();
            IDataTransferFactory.RegisterChannel();
        }

        private void frmWaiter_Load(object sender, EventArgs e)
        {
            //tabControlContent.ItemSize = new System.Drawing.Size(0, 1);
            DTO = IDataTransferFactory.getDataTransferObject(Properties.Settings.Default.RemoteObjAddress);

            dataSetRA.Relations.Remove("FK__OrderItem__Sessi__2E1BDC42");

            LoginDialog fLogin = new LoginDialog();

            bool loginOK = false;

            while (!loginOK)
            {
                if (!fLogin.getLogin())
                {
                    Application.ExitThread();
                    return;
                }

                try
                {
                    currWaiter = DTO.login(fLogin.UserName, fLogin.Password);
                    loginOK = currWaiter > 0 && DTO.isWaiter(currWaiter);
                }
                catch (Exception)
                {
                    loginOK = false;
                }
            }

            tabControlContent.SelectedTab = pageTables;
            loadData();
            cbTables.DataSource = tablelist;
            cbTables.DisplayMember = "TableName";
            cbTables.ValueMember = "ID";
            loadReadyItems();
            tablesManagement1.pnlControl.Enabled = false;
            DataTable tables = DTO.getTables();
            foreach (DataRow row in tables.Rows)
            {
                dataSetRA._Tables.Rows.Add(row.ItemArray);
            }
            tablesManagement1.SetSource(dataSetRA, null);
            timer.Enabled = true;
        }

        private void loadData()
        {
            dataSetRA.Clear();

            DataTable statusList = DTO.getOrderStatusList();
            foreach (DataRow row in statusList.Rows)
            {
                dataSetRA.OrderStatus.Rows.Add(row.ItemArray);
            }

            DataTable categories = DTO.getCategories();
            lvProducts.Groups.Clear();

            foreach (DataRow row in categories.Rows)
            {
                lvProducts.Groups.Add(row["ID"].ToString(), (string)row["Name"]);

                RADB.DataSetRA.CategoriesRow catRow = dataSetRA.Categories.NewCategoriesRow();
                catRow.ID = (int)row["ID"];
                catRow.Name = (string)row["Name"];
                dataSetRA.Categories.AddCategoriesRow(catRow);
            }
            DataTable products = DTO.getProducts();

            productImages.Images.Clear();
            lvProducts.Items.Clear();
            foreach (DataRow row in products.Rows)
            {
                if (row["Image"] != DBNull.Value)
                {
                    MemoryStream mstream = new MemoryStream((Byte[])row["Image"]);
                    Image img = Image.FromStream(mstream);
                    productImages.Images.Add(row["ID"].ToString(), img);
                    ListViewItem item = lvProducts.Items.Add(row["ID"].ToString(), (string)row["Name"], productImages.Images.Count - 1);
                    lvProducts.Groups[row["Category"].ToString()].Items.Add(item);
                }
                else
                {
                    ListViewItem item = lvProducts.Items.Add(row["ID"].ToString(), (string)row["Name"], -1);

                    if (lvProducts.Groups[row["Category"].ToString()] != null)
                    {
                        lvProducts.Groups[row["Category"].ToString()].Items.Add(item); 
                    }
                }

                DataSetRA.ProductsRow pRow = dataSetRA.Products.NewProductsRow();
                pRow.ID = (int)row["ID"];
                pRow.Name = (string)row["Name"];
                if (row["Category"] != DBNull.Value)
                {
                    pRow.Category = (int)row["Category"];
                }
                pRow.MenuPrice = (decimal)row["MenuPrice"];
                pRow.Available = true;
                dataSetRA.Products.AddProductsRow(pRow);
            }
            dataSetRA.Products.AcceptChanges();

            tablelist = DTO.getTables();
            lvReadyItems.Groups.Clear();
            foreach (DataRow row in tablelist.Rows)
            {
                lvReadyItems.Groups.Add(row["ID"].ToString(), (string)row["TableName"]);
            }


            /*
            public const int EmpManager = 1;
            public const int EmpHost = 2;
            public const int EmpWaiter = 3;
            public const int EmpCook = 4;
            public const int EmpBusBoy = 5;
            public const int tableAvailable = 1;
            public const int tableReserved = 2;
            public const int tableWaiting = 3;
            public const int tableOccupied = 4;
            public const int tableDirty = 5;
            public const int tableCleaning = 6;
            public const int orderWaiting = 1;
            public const int orderCooking = 2;
            public const int orderReady = 3;
            public const int orderCanncelled = 4;
            public const int orderDelivered = 5;
             */
            lvTables.Groups.Add("3", "Waiting");
            lvTables.Groups.Add("4", "Occupied");
            lvTables.Groups.Add("0", "Others");
            ListViewGroup viewGroup = null;
            ListViewItem viewItem = null;
            foreach (DataRow row in tablelist.Rows)
            {
                viewItem = lvTables.Items.Add(row["ID"].ToString(), row["TableName"].ToString(), 0);
                viewGroup = lvTables.Groups[row["Status"].ToString()];
                if (viewGroup == null)
                {
                    viewGroup = lvTables.Groups["0"];
                }
                viewItem.Group = viewGroup;
            }
        }


        private void loadTableStatus()
        {
            DataTable tables = null;

            try
            {
                tables = DTO.getTables();
            }
            catch (Exception)
            {
                timer.Enabled = false;
                MessageBox.Show("Cannot connect to server", "Server error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                timer.Enabled = true;
                return;
            }

            ListViewGroup viewGroup = null;
            ListViewItem viewItem = null;
            int status = 0;
            foreach (DataRow row in tables.Rows)
            {
                viewItem = lvTables.Items[row["ID"].ToString()];
                status = (int)row["Status"];
                if (status != 3 && status != 4)
                {
                    status = 0;
                }
                if (viewItem != null && status.ToString() != viewItem.Group.Name)
                {
                    viewItem.Group = lvTables.Groups[status.ToString()];
                }
            }


            List<int> tablelist = new List<int>();
            List<DataSetRA.TablesRow> removeList = new List<DataSetRA.TablesRow>();
            foreach (DataRow row in tables.Rows)
            {
                DataSetRA.TablesRow tRow = dataSetRA._Tables.FindByID((int)row["ID"]);
                if (tRow == null)
                {
                    dataSetRA._Tables.Rows.Add(row.ItemArray);
                }
                else
                {
                    if (tRow.Status != (int)row["status"])
                    {
                        tRow.Status = (int)row["status"];
                    }
                    if (tRow.PosX != (double)row["PosX"])
                    {
                        tRow.PosX = (double)row["PosX"];
                    }
                    if (tRow.PosY != (double)row["PosY"])
                    {
                        tRow.PosY = (double)row["PosY"];
                    }
                }
                tablelist.Add(tRow.ID);
            }
            foreach (DataSetRA.TablesRow row in dataSetRA._Tables)
            {
                if (tablelist.IndexOf(row.ID) < 0)
                {
                    removeList.Add(row);
                }
            }
            foreach (DataSetRA.TablesRow row in removeList)
            {
                dataSetRA._Tables.RemoveTablesRow(row);
            }
        }
        private void loadReadyItems()
        {
            DataTable readyItems = null;
            try
            {
                readyItems = DTO.getReadyItems();
            }
            catch (Exception)
            {
                timer.Enabled = false;
                MessageBox.Show("Cannot connect to server", "Server error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                timer.Enabled = true;
                return;
            }
            ListViewItem viewItem;
            List<ListViewItem> removeItems = new List<ListViewItem>();
            ListViewGroup viewGroup;
            //lvReadyItems.Clear();            
            foreach (ListViewItem item in lvReadyItems.Items)
            {
                try
                {
                    if (readyItems.Rows.Find(int.Parse(item.Name)) == null)
                    {
                        removeItems.Add(item);
                    }
                }
                catch (Exception)
                {
                    removeItems.Add(item);
                }
            }
            foreach (ListViewItem item in removeItems)
            {
                lvReadyItems.Items.Remove(item);
            }

            foreach (DataRow row in readyItems.Rows)
            {
                if (lvReadyItems.Items[row["ID"].ToString()] == null)
                {
                    RADB.DataSetRA.ProductsRow pRow = dataSetRA.Products.FindByID((int)row["Product"]);
                    if (pRow != null)
                    {
                        viewItem = lvReadyItems.Items.Add(row["ID"].ToString(), string.Format("{0} ({1})", pRow.Name, row["Quantity"]), pRow.ID.ToString());
                        viewGroup = lvReadyItems.Groups[row["Table"].ToString()];
                        if (viewGroup != null)
                        {
                            viewGroup.Items.Add(viewItem);
                        }
                    }
                }

            }
        }

        private void lvProducts_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void lvProducts_ItemActivate(object sender, EventArgs e)
        {
            if (lvProducts.SelectedItems.Count == 0)
            {
                return;
            }
            int itemId = int.Parse(lvProducts.SelectedItems[0].Name);
            RADB.DataSetRA.OrderItemsRow row = dataSetRA.OrderItems.FindByID(-itemId);
            if (row == null)
            {
                row = dataSetRA.OrderItems.NewOrderItemsRow();
                row.ID = -itemId;
                row.Product = itemId;
                row.Status = 1;
                row.Price = dataSetRA.Products.FindByID(itemId).MenuPrice;
                row.Quantity = 1;
                row.Session = 1;
                row.PlacingTime = DateTime.Now;
                dataSetRA.OrderItems.AddOrderItemsRow(row);
            }
            else
            {
                row.Quantity++;
            }
        }

        private void gvOrder_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (gvOrder.OptionsBehavior.Editable)
                {
                    gvOrder.DeleteSelectedRows();
                }
                else
                {
                    int[] rows = gvOrder.GetSelectedRows();
                    if (rows.Length == 1)
                    {
                        RADB.DataSetRA.OrderItemsRow row = (RADB.DataSetRA.OrderItemsRow)gvOrder.GetDataRow(rows[0]);
                        if (row.Status == 1)
                        {
                            if (MessageBox.Show("Are you sure you wish to cancel this order ?", "Cancel", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                            {
                                row.Status = 4;
                            }
                        }
                    }
                }
            }
        }

        private void btnPlaceOrder_Click(object sender, EventArgs e)
        {

            bool resOp = true;
            OrderItemDTO info = new OrderItemDTO();
            foreach (RADB.DataSetRA.OrderItemsRow row in dataSetRA.OrderItems)
            {
                if ((int)row["ID"] > 0) //ordered in previous times.
                {
                    if ((int)row["Status"] == 4)
                    {
                        DTO.cancelAnOrder((int)row["ID"]);
                    }
                    continue;
                }
                info.productID = row.Product;
                info.quantity = row.Quantity;
                info.tableID = (int)cbTables.SelectedValue;
                try
                {
                    resOp = DTO.placeAnOrder(currWaiter, info);
                }
                catch (Exception)
                {
                    resOp = false;
                }

                if (!resOp)
                {
                    MessageBox.Show("Cannot place order", "Server error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }
            if (resOp)
            {
                reloadOrderedItems();
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            reloadOrderedItems();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            loadReadyItems();
            loadTableStatus();
        }

        private void lvReadyItems_ItemActivate(object sender, EventArgs e)
        {
            bool resOp = true;
            if (lvReadyItems.SelectedItems.Count > 0)
            {
                int itemId = int.Parse(lvReadyItems.SelectedItems[0].Name);
                try
                {
                    resOp = DTO.deliverAnItem(currWaiter, itemId);
                }
                catch (Exception)
                {
                    resOp = false;
                }

                if (resOp)
                {
                    lvReadyItems.Items.Remove(lvReadyItems.SelectedItems[0]);
                }
                else
                {
                    MessageBox.Show("Cannot deliver this item. It is possible that another waiter has taken this item.", "Deliver Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void lvTables_ItemActivate(object sender, EventArgs e)
        {
            bool resOp = true;
            ListViewItem viewItem = null;
            if (lvTables.SelectedItems.Count > 0)
            {
                viewItem = lvTables.SelectedItems[0];
                int itemId = int.Parse(viewItem.Name);
                switch (viewItem.Group.Name)
                {
                    case "3":
                        try
                        {
                            resOp = DTO.setTableOccupied(itemId);
                        }
                        catch (Exception)
                        {
                            resOp = false;
                        }
                        if (!resOp)
                        {
                            MessageBox.Show("Cannot choose this table. It is possible that another waiter has taken this table.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return;
                        }
                        else
                        {
                            viewItem.Group = lvTables.Groups["4"];
                        }
                        cbTables.SelectedValue = itemId;
                        tabControlContent.SelectedTab = pagePlaceOrder;
                        break;
                    case "4":
                        cbTables.SelectedValue = itemId;
                        tabControlContent.SelectedTab = pagePlaceOrder;
                        break;
                    //case "4":
                    //    try
                    //    {
                    //        resOp = DTO.setTableDirty(itemId);
                    //    }
                    //    catch (Exception)
                    //    {
                    //        resOp = false;
                    //    }
                    //    if (!resOp)
                    //    {
                    //        MessageBox.Show("Cannot choose this table. It is possible that another waiter has taken this table.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    //        return;
                    //    }
                    //    else
                    //    {
                    //        viewItem.Group = lvTables.Groups["0"];
                    //    }
                    //    break;
                    default:
                        break;
                }
            }
        }

        private void cbTables_SelectedValueChanged(object sender, EventArgs e)
        {
            reloadOrderedItems();
        }

        private void reloadOrderedItems()
        {
            dataSetRA.OrderItems.Clear();
            try
            {
                DataTable orderedItems = DTO.getOrderedItems((int)cbTables.SelectedValue);
                foreach (DataRow row in orderedItems.Rows)
                {
                    dataSetRA.OrderItems.Rows.Add(row.ItemArray);
                }
            }
            catch (Exception)
            {
                return;
            }
        }

        private void gvOrder_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e)
        {
            DataRow row = ((DataRowView)e.Row).Row;
            if ((int)row["ID"] > 0)
            {
                e.ErrorText = "Cannot change ordered items in previous times";
                e.Valid = false;
            }
        }

        private void gvOrder_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            DataRow row = gvOrder.GetDataRow(e.FocusedRowHandle);
            gvOrder.OptionsBehavior.Editable = row != null && (int)row["ID"] < 0;

        }

        private void btnBill_Click(object sender, EventArgs e)
        {
            reloadOrderedItems();
            //foreach (RADB.DataSetRA.OrderItemsRow row in dataSetRA.OrderItems)
            //{
            //    DTO.deliverAnItem(currWaiter, row.ID);
            //    DTO.cancelAnOrder(row.ID);
            //}

            bool resOp = true;
            int table = (int)cbTables.SelectedValue;
            try
            {
                resOp = DTO.setTableDirty(table);
            }
            catch (Exception)
            {
                resOp = false;
            }
            if (!resOp)
            {
                MessageBox.Show("Cannot choose this table. It is possible that another waiter has taken this table.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            else
            {
                lvTables.Items[table.ToString()].Group = lvTables.Groups["0"];
                dataSetRA.OrderItems.Clear();
            }
        }

        private void gvOrder_CustomSummaryCalculate(object sender, DevExpress.Data.CustomSummaryEventArgs e)
        {
            //
        }

        private void tablesManagement1_TableDoubleClick(int tableid, _TablesManagement.Table.TableStatus status)
        {
            bool resOp = true;

            switch (status)
            {
                case _TablesManagement.Table.TableStatus.Available:
                    break;
                case _TablesManagement.Table.TableStatus.Reserved:
                    break;
                case _TablesManagement.Table.TableStatus.Waiting:
                    try
                    {
                        resOp = DTO.setTableOccupied(tableid);
                    }
                    catch (Exception)
                    {
                        resOp = false;
                    }
                    if (!resOp)
                    {
                        MessageBox.Show("Cannot choose this table. It is possible that another waiter has taken this table.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    else
                    {
                        dataSetRA._Tables.FindByID(tableid).Status = 4;
                    }
                    cbTables.SelectedValue = tableid;
                    tabControlContent.SelectedTab = pagePlaceOrder;
                    break;
                case _TablesManagement.Table.TableStatus.Occupied:
                    cbTables.SelectedValue = tableid;
                    tabControlContent.SelectedTab = pagePlaceOrder;
                    break;
                case _TablesManagement.Table.TableStatus.Dirty:
                    break;
                case _TablesManagement.Table.TableStatus.Cleaning:
                    break;
                default:
                    break;
            }            
        }
    }
}